package com.tomtop.core.utils;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
 * 
 * @author lenovo
 * 方法介绍
 * 	n 		: 创建
 * 	a 		: 添加
 *  ck  	: 判断key是否存在
 *  cv  	: 判断是否存在
 *  r  		: 删除
 *  c  		: 清理
 *  s  		: 大小
 *  g		: 取出
 *  to  	: 转化为原型
 *  each  	: 遍历
 *  filter  : 过滤
 *  array  	: 转化为列表
 *  map		: 重写map的值对象
 *  mapKey  : 重写key对象
 * @param <K>
 * @param <V>
 */
public class MapUtils<K,V>{

	@FunctionalInterface public static interface EachMap<K,V> { void accept(K k,V v); }
	@FunctionalInterface public static interface FilterMap<K,V> { boolean test(K k,V v); }
	@FunctionalInterface public static interface ArrayMap<K,V,T> { T accept(K k,V v); }
	@FunctionalInterface public static interface ArraysMap<K,V,T> { Collection<T> accept(K k,V v); }
	@FunctionalInterface public static interface MapNewMap<K,V,T> { T accept(K k,V v); }
	
	
	private Map<K,V> map;

	private MapUtils() {
		map = new HashMap<>();
	}

	private MapUtils(Map<K, V> map) {
		this();
		if(map!=null&&map.size()>0)
			this.map.putAll(map);
	}

	public static <K, V> MapUtils<K, V> n() {
		return new MapUtils<K, V>();
	}

	public static <K, V> MapUtils<K, V> n(Map<K, V> map) {
		return new MapUtils<K, V>(map);
	}

	public MapUtils<K, V> a(K key, V value) {
		map.put(key, value);
		return this;
	}

	public V g(K key) {
		return map.get(key);
	}
	public ListUtils<V> g(@SuppressWarnings("unchecked") K ...keys) {
		ListUtils<V> lu= ListUtils.n();
		for (K k : keys) {
			V v=this.g(k);
			lu.a(v);
		}
		return lu;
	}

	public  MapUtils<K, V>  r(K key) {
		map.remove(key);
		return this;
	}
	
	public  MapUtils<K, V>  r(@SuppressWarnings("unchecked") K ... keys) {
		for (K key : keys) {
			map.remove(key);
		}
		return this;
	}
	
	public MapUtils<K, V> c(K key, V value) {
		map.clear();
		return this;
	}

	public Map<K, V> to() {
		return map;
	}

	public boolean ck(K key) {
		return map.containsKey(key);
	}

	public int s() {
		return map.size();
	}

	public boolean cv(V value) {
		return map.containsValue(value);
	}
	
	public MapUtils<K, V> each(EachMap<K, V> eachMap) {
		  this.map.forEach((k,v)->{
			  eachMap.accept(k, v);
		  });
		return this;
	}

	public MapUtils<K, V> filter(FilterMap<K, V> filter) {
		MapUtils<K, V> mu=MapUtils.n();
		this.each((k,v)->{
			if(filter.test(k, v)){
				mu.a(k, v);
			}
		});
		return mu;
	}

	public <N> MapUtils<K, N> map(MapNewMap<K, V, N> mnm) {
		MapUtils<K, N> mu=MapUtils.n();
		this.each((k,v)->{
			N val = mnm.accept(k, v);
			if(val!=null)
				mu.a(k, val);
		});
		return mu;
	}
	public <NK> MapUtils<NK, V> mapKey(MapNewMap<K, V, NK> mnm) {
		MapUtils<NK, V> mu=MapUtils.n();
		this.each((k,v)->{
			NK nk = mnm.accept(k, v);
			if(nk!=null)
				mu.a(nk, v);
		});
		return mu;
	}

	public <T> ListUtils<T> array(ArrayMap<K,V,T> am) {
		ListUtils<T> lu=ListUtils.n();
		this.each((k,v)->{
			T t = am.accept(k, v);
			if(t!=null)
				lu.a(t);
		});
		return lu;
	}
	
	public <T> ListUtils<T> arrays(ArraysMap<K,V,T> am) {
		ListUtils<T> lu=ListUtils.n();
		this.each((k,v)->{
			lu.a(am.accept(k, v));
		});
		return lu;
	}
	
	public static boolean isNotEmpty(Map<?,?> ... args) {
		for (Map<?,?> map : args) {
			if(map==null||map.isEmpty())
				return false;
		}
		return true;
	}
	public static boolean isEmpty(Map<?,?> ...args) {
		return !isNotEmpty(args);
	}
}